#include "waitforack.h"
#include "macro.h"
#include <QTimer>
#define TIMER_GAP_MS 1000

WaitForAck::WaitForAck(QObject *parent) :
    QObject(parent)
{
    timerOfResend=new QTimer(this);
    timerOfResend->start(TIMER_GAP_MS);
    connect(timerOfResend,SIGNAL(timeout()),this,SLOT(timerEventOfResend()));

}

void WaitForAck::addOnePacket(qint64 nodeAddr, quint8 sN, QByteArray packet)
{
    QByteArray baAddrSN=QByteArray::number(nodeAddr)+":"+QByteArray::number(sN);
    if(mapAddrSNConfTTL.contains(baAddrSN))
        return;

    mapAddrSNConfTTL.insert(baAddrSN,WaitACK_TTL_MAX);
    mapAddrSNSentTime.insert(baAddrSN,WaitACK_Resend_Gap);
    mapAddrSNConfData.insert(baAddrSN,packet);
}

void WaitForAck::removeOnePacket(qint64 nodeAddr, quint8 sN)
{
    QByteArray baAddrSN=QByteArray::number(nodeAddr)+":"+QByteArray::number(sN);
    mapAddrSNConfTTL.remove(baAddrSN);
    mapAddrSNSentTime.remove(baAddrSN);
    mapAddrSNConfData.remove(baAddrSN);
}

void WaitForAck::timerEventOfResend()
{
    QMapIterator<QByteArray,qint16> i(mapAddrSNSentTime);
    if(WaitACK_TTL_MAX<=0)
        return;

    while (i.hasNext())
    {
        i.next();
        qint16 curTime= i.value();
        QByteArray curAddrSN=i.key();
        if(curTime<=0)
        {
           qint16 curTTL=mapAddrSNConfTTL.value(curAddrSN);
           if(curTTL<=0)  // 已经重传了多次，仍然没有回复
           {
              emit sigErrorInfo("ERROR from waitForACK: Config packet reply not received from "+curAddrSN+
                        "\nPacket is "+mapAddrSNConfData.value(curAddrSN).toHex());
               mapAddrSNConfTTL.remove(curAddrSN);
               mapAddrSNSentTime.remove(curAddrSN);
               mapAddrSNConfData.remove(curAddrSN);
           }
           else
           {
               qint64 mask= Q_INT64_C(0x00ffffffffffffff);
               qint64 destNodeAddr=curAddrSN.split(':').at(0).toLongLong();
               emit sigPacketToNodeAgain(mapAddrSNConfData.value(curAddrSN),destNodeAddr&mask); //重新发送一次
               emit sigErrorInfo(tr("向节点").toUtf8()+QByteArray::number(destNodeAddr)+tr("重传了配置包：").toUtf8()+mapAddrSNConfData.value(curAddrSN));
                mapAddrSNConfTTL.insert(curAddrSN,curTTL-1);
                mapAddrSNSentTime.insert(curAddrSN,WaitACK_Resend_Gap);
           }
        }
        else
        {
            mapAddrSNSentTime.insert(curAddrSN,curTime-1);
        }
    }
}
